package saati.core.statistic.fisher;


import com.numericalmethod.suanshu.stats.distribution.univariate.FDistribution;
import org.apache.commons.math.MathException;
import org.apache.commons.math.distribution.FDistributionImpl;
import saati.core.statistic.Checker;

public class FisherChecker implements Checker {
    private static final double probability = 0.05d;

    public boolean checkTheory(int m, int n, double concordance) {
        double fP = calculateFP(m, concordance);
        FreedomDegrees degrees = calculateDegreesOfFreedom(m, n);
        double fisherDistribution = calculateFisherDestribution(degrees.f1, degrees.f2);
        return (fP >= fisherDistribution);
    }

    public double calculateFisherDestribution(double f1, double f2) {
        FDistributionImpl distribution = new FDistributionImpl(f1, f2);
        try {
            return distribution.inverseCumulativeProbability(1-probability);
        } catch (MathException e) {
            return 0;
        }
    }

    private static FreedomDegrees calculateDegreesOfFreedom(int m, int n) {
        double f1 = n - 1 - 2 / m;
        double f2 = (m - 1) / f1;
        return new FreedomDegrees(f1, f2);
    }

    private static double calculateFP(int m, double concordance) {
        return ((0.5 * Math.log(m - 1) * concordance) / (1 - concordance));
    }

    private static class FreedomDegrees {
        private double f1;
        private double f2;

        private FreedomDegrees(double f1, double f2) {
            this.f1 = f1;
            this.f2 = f2;
        }

        public double getF1() {
            return f1;
        }

        public void setF1(double f1) {
            this.f1 = f1;
        }

        public double getF2() {
            return f2;
        }

        public void setF2(double f2) {
            this.f2 = f2;
        }
    }
}
